/**
 * 
 */
package com.dalonedrow.engine.ui.base.border;

import com.dalonedrow.globalvariables.constants.hq.GlobalConstants;

/**
 * Factory class for producing standardized UI widget borders.
 * @author Donald
 */
public class BorderFactory {
	/** the one and only instance of the <code>BorderFactory</code> class. */
	private static BorderFactory	instance;
	/**
	 * BorderFactory Gives access to the singleton instance of
	 * {@link BorderFactory}.
	 * @return {@link BorderFactory}
	 */
	public static BorderFactory getInstance() {
		if (BorderFactory.instance == null) {
			BorderFactory.instance = new BorderFactory();
		}
		return BorderFactory.instance;
	}
	/** Hidden constructor. */
	private BorderFactory() {}
	/**
	 * Gets a custom border.
	 * @param insets the border's insets. Cannot be null.
	 * @param cornerImages the set of images used to render the outer border.
	 *        May be null.
	 * @param backgroundImages the set of images used to render the border's
	 *        inner background. May be null.
	 * @param backgroundColor1 the border's first background color. May be null.
	 * @param backgroundColor2 the border's second background color. Using two
	 *        colors will produce a gradient background. May be null.
	 * @param backgroundLines if true, the border's inner background will have
	 *        vertical lines
	 * @param middleOffsets the offsets for the inner background color or
	 *        images. May be null.
	 * @return {@link GuiBorder}
	 * @throws Exception if an error occurs
	 */
	private GuiBorder getBorder(final int[] insets,
			final String[] cornerImages,
			final String[] backgroundImages, final float[] backgroundColor1,
			final float[] backgroundColor2, final boolean backgroundLines,
			final int[] middleOffsets) throws Exception {
		GuiBorder border = null;
		if (insets == null
				|| insets != null
				&& insets.length != GlobalConstants.INT_004) {
			throw new Exception("Need 4 values for border insets.");
		}
		if (middleOffsets != null
				&& middleOffsets.length != 2) {
			throw new Exception(
					"Only 2 values allowed for background offsets.");
		}
		if (cornerImages != null
				&& cornerImages.length != GlobalConstants.INT_008) {
			throw new Exception("Need 8 values for corner images.");
		}
		if (backgroundColor1 != null
				&& backgroundColor1.length != GlobalConstants.INT_003
				&& backgroundColor1.length != GlobalConstants.INT_004) {
			throw new Exception("Need 3 or 4 values background color.");
		}
		if (backgroundColor1 != null
				&& backgroundColor1.length != GlobalConstants.INT_003
				&& backgroundColor1.length != GlobalConstants.INT_004) {
			throw new Exception("Need 3 or 4 values background color.");
		}
		if (cornerImages != null
				&& backgroundImages != null
				&& backgroundColor1 != null) {
			// 8x4 image background
			if (middleOffsets == null) {
				border = new Abstract8x4ImageBorder(insets, cornerImages,
						backgroundImages, backgroundColor1);
			} else {
				border = new Abstract8x4ImageBorder(insets, cornerImages,
						backgroundImages, backgroundColor1, middleOffsets[0],
						middleOffsets[1]);
			}
		} else if (cornerImages != null) {
			if (backgroundColor1 != null) {
				// 8 image borders
				if (backgroundLines) {
					if (backgroundColor2 != null) {
						// lines and gradient
						if (middleOffsets == null) {
							border = new Abstract8ImageBorderWithLinesAndGradient(
									insets, cornerImages, backgroundColor1,
									backgroundColor2);
						} else {
							border = new Abstract8ImageBorderWithLinesAndGradient(
									insets, cornerImages, backgroundColor1,
									backgroundColor2, middleOffsets[0],
									middleOffsets[1]);
						}
					} else {
						// lines
						if (middleOffsets == null) {
							border = new Abstract8ImageBorderWithLines(
									insets, cornerImages, backgroundColor1);
						} else {
							border = new Abstract8ImageBorderWithLines(
									insets, cornerImages, backgroundColor1,
									middleOffsets[0], middleOffsets[1]);
						}
					}
				} else {
					// no lines
					if (middleOffsets == null) {
						border = new Abstract8ImageBorder(
								insets, cornerImages, backgroundColor1);
					} else {
						border = new Abstract8ImageBorder(
								insets, cornerImages, backgroundColor1,
								middleOffsets[0], middleOffsets[1]);
					}
				}
			} else {
				// 8 border image, no background
				if (middleOffsets == null) {
					border = new Abstract8ImageNoBackgroundBorder(
							insets, cornerImages);
				} else {
					border = new Abstract8ImageNoBackgroundBorder(
							insets, cornerImages,
							middleOffsets[0], middleOffsets[1]);
				}
			}
		} else if (backgroundColor1 != null) {
			// 1 color background
			if (backgroundLines) {
				// lines
				if (middleOffsets == null) {
					border = new Abstract1ColorWithLinesBorder(insets,
							backgroundColor1);
				} else {
					border = new Abstract1ColorWithLinesBorder(insets,
							backgroundColor1,
							middleOffsets[0], middleOffsets[1]);
				}

			} else {
				// no lines
				if (middleOffsets == null) {
					border = new Abstract1ColorBorder(insets, backgroundColor1);
				} else {
					border = new Abstract1ColorBorder(insets, backgroundColor1,
							middleOffsets[0], middleOffsets[1]);
				}
			}
		}
		return border;
	}
	/**
	 * Gets a simple border made up of a 1-color background and no outside
	 * edges.
	 * @param insets the border insets
	 * @param backgroundColor the background color
	 * @return {@link GuiBorder}
	 * @throws Exception if an error occurs
	 */
	public GuiBorder getBorder1ColorBackground(final int[] insets,
			final float[] backgroundColor) throws Exception {
		return getBorder(insets, null, null, backgroundColor, null, false,
				null);
	}
	/**
	 * Gets a simple border made up of a 1-color background with vertical lines
	 * and no outside edges.
	 * @param insets the border insets
	 * @param backgroundColor the background color
	 * @return {@link GuiBorder}
	 * @throws Exception if an error occurs
	 */
	public GuiBorder getBorder1ColorBackgroundWithLines(final int[] insets,
			final float[] backgroundColor) throws Exception {
		return getBorder(insets, null, null, backgroundColor, null, true,
				null);
	}
	/**
	 * Gets a border made up of an edge drawn from 8 images and no background.
	 * @param insets the border insets
	 * @param cornerImages the set of images used to render the outer border
	 * @return {@link GuiBorder}
	 * @throws Exception if an error occurs
	 */
	public GuiBorder getBorderEdgeOf8Images(final int[] insets,
			final String[] cornerImages) throws Exception {
		return getBorder(insets, cornerImages, null, null, null, false,
				null);
	}
	/**
	 * 
	 * @param parent the parent component
	 * @param imgName the name of the highlight image
	 * @return {@link GuiBorder}
	 */
	public GuiBorder getHighlightBorder(final int parent, final String imgName) 
	{
		return new AbstractHighlightBorder(parent, imgName);
	}
	/**
	 * Gets a border made up of an edge drawn from 8 images and 1-color
	 * background.
	 * @param insets the border insets
	 * @param cornerImages the set of images used to render the outer border
	 * @param backgroundColor the background color
	 * @return {@link GuiBorder}
	 * @throws Exception if an error occurs
	 */
	public GuiBorder getBorderEdgeOf8ImagesBackgroundOf1Color(
			final int[] insets, final String[] cornerImages, 
			final float[] backgroundColor) throws Exception {
		return getBorder(insets, cornerImages, null, backgroundColor, null,
				false, null);
	}
	/**
	 * Gets a border made up of an edge drawn from 8 images and 1-color
	 * background.
	 * @param insets the border insets
	 * @param cornerImages the set of images used to render the outer border
	 * @param backgroundColor the background color
	 * @param xOffset the x-offset for the inner background color
	 * @param yOffset the y-offset for the inner background color
	 * @return {@link GuiBorder}
	 * @throws Exception if an error occurs
	 */
	public GuiBorder getBorderEdgeOf8ImagesBackgroundOf1Color(
			final int[] insets, final String[] cornerImages, 
			final float[] backgroundColor, final int xOffset, final int yOffset)
					throws Exception {
		return getBorder(insets, cornerImages, null, backgroundColor, null,
				false, new int[] { xOffset, yOffset });
	}
	/**
	 * Gets a border made up of an edge drawn from 8 images and 1-color
	 * background with vertical lines.
	 * @param insets the border insets
	 * @param cornerImages the set of images used to render the outer border
	 * @param backgroundColor the background color
	 * @return {@link GuiBorder}
	 * @throws Exception if an error occurs
	 */
	public GuiBorder getBorderEdgeOf8ImagesBackgroundOf1ColorWithLines(
			final int[] insets, final String[] cornerImages, 
			final float[] backgroundColor) throws Exception {
		return getBorder(insets, cornerImages, null, backgroundColor, null,
				true, null);
	}
	/**
	 * Gets a border made up of an edge drawn from 8 images and 2-color
	 * gradient background.
	 * @param insets the border insets
	 * @param cornerImages the set of images used to render the outer border
	 * @param backgroundColor1 the first background gradient color
	 * @param backgroundColor2 the second background gradient color
	 * @return {@link GuiBorder}
	 * @throws Exception if an error occurs
	 */
	public GuiBorder getBorderEdgeOf8Images2ColorGradientBackground(
			final int[] insets, final String[] cornerImages, 
			final float[] backgroundColor1, final float[] backgroundColor2)
			throws Exception {
		return getBorder(insets, cornerImages, null, backgroundColor1, 
				backgroundColor2, false, null);
	}
	/**
	 * Gets a border made up of an edge drawn from 8 images and 2-color
	 * gradient background with vertical lines.
	 * @param insets the border insets
	 * @param cornerImages the set of images used to render the outer border
	 * @param backgroundColor1 the first background gradient color
	 * @param backgroundColor2 the second background gradient color
	 * @return {@link GuiBorder}
	 * @throws Exception if an error occurs
	 */
	public GuiBorder getBorderEdgeOf8Images2ColorGradientBackgroundWithLines(
			final int[] insets, final String[] cornerImages, 
			final float[] backgroundColor1, final float[] backgroundColor2)
			throws Exception {
		return getBorder(insets, cornerImages, null, backgroundColor1, 
				backgroundColor2, true, null);
	}
	/**
	 * Gets a border made up of an edge drawn from 8 images and 2-color
	 * gradient background with vertical lines.
	 * @param insets the border insets
	 * @param cornerImages the set of images used to render the outer border
	 * @param backgroundColor1 the first background gradient color
	 * @param backgroundColor2 the second background gradient color
	 * @param xOffset the x-offset for the inner background color
	 * @param yOffset the y-offset for the inner background color
	 * @return {@link GuiBorder}
	 * @throws Exception if an error occurs
	 */
	public GuiBorder getBorderEdgeOf8Images2ColorGradientBackgroundWithLines(
			final int[] insets, final String[] cornerImages, 
			final float[] backgroundColor1, final float[] backgroundColor2, 
			final int xOffset, final int yOffset)
			throws Exception {
		return getBorder(insets, cornerImages, null, backgroundColor1, 
				backgroundColor2, true, new int[] { xOffset, yOffset });
	}
	/**
	 * Gets a border made up of an edge drawn from 8 images and 4-image
	 * background.
	 * @param insets the border insets
	 * @param cornerImages the set of images used to render the outer border
	 * @param backgroundImages the set of images used to render the inner 
	 * background
	 * @param backgroundColor the first background color, used to fill in areas 
	 * the inner images do not cover
	 * @return {@link GuiBorder}
	 * @throws Exception if an error occurs
	 */
	public GuiBorder getBorderEdgeOf8Images4ImageBackground(
			final int[] insets, final String[] cornerImages, 
			final String[] backgroundImages, final float[] backgroundColor)
			throws Exception {
		return getBorder(insets, cornerImages, backgroundImages,
				backgroundColor, null, true, null);
	}
	/**
	 * Gets a border made up of an edge drawn from 8 images and 4-image
	 * background.
	 * @param insets the border insets
	 * @param cornerImages the set of images used to render the outer border
	 * @param backgroundImages the set of images used to render the inner 
	 * background
	 * @param backgroundColor the first background color, used to fill in areas 
	 * the inner images do not cover
	 * @param xOffset the x-offset for the inner background
	 * @param yOffset the y-offset for the inner background
	 * @return {@link GuiBorder}
	 * @throws Exception if an error occurs
	 */
	public GuiBorder getBorderEdgeOf8Images4ImageBackground(
			final int[] insets, final String[] cornerImages, 
			final String[] backgroundImages, final float[] backgroundColor,
			final int xOffset, final int yOffset) throws Exception {
		return getBorder(insets, cornerImages, backgroundImages,
				backgroundColor, null, true, new int[] { xOffset, yOffset });
	}
}
